package com.jp.fm.servlet;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertNotNull;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.jp.fm.EasyMockParent;
import com.jp.fm.dao.AccountDao;
import com.jp.fm.dao.BudgetDao;
import com.jp.fm.dao.CategoryDao;
import com.jp.fm.dao.TransactionDao;
import com.jp.fm.data.Account;
import com.jp.fm.data.Category;
import com.jp.fm.data.Transaction;
import com.jp.fm.service.BudgetService;
import com.jp.fm.service.CategoryService;
import com.jp.fm.service.PageService;
import com.jp.fm.service.TransactionService;

public class ShowTransactionsTest extends EasyMockParent {

	private ShowTransactions servlet = null;

	private HttpServletRequest mockRequest = null;
	private HttpServletResponse mockResponse = null;
	private AccountDao mockAccountDao = null;
	private CategoryDao mockCategoryDao = null;
	private BudgetDao mockBudgetDao = null;
	private TransactionDao mockTransactionDao = null;
	private TransactionService mockTransactionService = null;
	private CategoryService mockCategoryService = null;
	private BudgetService mockBudgetService = null;
	private PageService mockPageService = null;
	private RequestDispatcher mockRequestDispatcher = null;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
		super.setUp();

		servlet = new ShowTransactions();
	}

	@After
	public void tearDown() throws Exception {
		super.tearDown();
	}

	@Test
	public final void testCreateCategoryIdArray() {

		servlet.setCategoryDao(mockCategoryDao);

		expect(mockCategoryDao.findByName(anyObject(String.class))).andReturn(
				new Category(99, "test1")).times(2);

		replayMocks();

		String[] ret = servlet.createCategoryIdArray(null,
				"Others: test1, test2");
		assertNotNull(ret);
	}

	@Test
	public final void testComposeTransactionsCurrentMonth() {
		servlet.setCategoryDao(mockCategoryDao);
		servlet.setTransactionDao(mockTransactionDao);
		servlet.setTransactionService(mockTransactionService);

		Category cat = new Category(null, "test");
		Transaction tran = new Transaction(null, 0, null, Float.valueOf("10"),
				null, null, null, false, null);
		List<Transaction> list = new ArrayList<Transaction>();
		list.add(tran);

		mockRequest.setAttribute(eq("category"), anyObject(String.class));
		EasyMock.expectLastCall();
		expect(mockCategoryDao.findByName("test")).andReturn(cat);
		expect(
				mockTransactionDao.findByAny(eq(cat), anyObject(Date.class),
						anyObject(Date.class), anyObject(String.class),
						anyObject(String.class), anyObject(Boolean.class)))
				.andReturn(list);
		expect(mockTransactionService.calculateTransactionsTotal(list, cat))
				.andReturn(Float.valueOf("10"));

		mockRequest.setAttribute(eq("categoryAmount"), anyObject(Float.class));
		EasyMock.expectLastCall();

		replayMocks();

		servlet.composeTransactionsCurrentMonth(mockRequest, "test");
	}

	@Test
	public final void testComposeTransactionsSearch() {

		servlet.setCategoryDao(mockCategoryDao);
		servlet.setTransactionDao(mockTransactionDao);
		servlet.setTransactionService(mockTransactionService);

		Date date = new Date();
		Category cat = new Category(null, "test");
		Transaction tran = new Transaction(null, 0, null, Float.valueOf("10"),
				null, null, null, false, null);
		List<Transaction> list = new ArrayList<Transaction>();
		list.add(tran);

		expect(mockCategoryDao.findById(1)).andReturn(cat);
		mockRequest.setAttribute(eq("category"), anyObject(String.class));
		EasyMock.expectLastCall();
		mockRequest.setAttribute("startDate", date);
		EasyMock.expectLastCall();
		mockRequest.setAttribute("endDate", date);
		EasyMock.expectLastCall();
		expect(
				mockTransactionDao.findByAny(cat, date, date, null, "keyword",
						null)).andReturn(list);
		expect(
				mockTransactionService.calculateTransactionsTotal(eq(list),
						anyObject(List.class))).andReturn(Float.valueOf("10"));

		mockRequest.setAttribute(eq("categoryAmount"), anyObject(Float.class));
		EasyMock.expectLastCall();
		mockRequest.setAttribute(eq("keyword"), anyObject(String.class));
		EasyMock.expectLastCall();

		replayMocks();

		servlet.composeTransactionsSearch(mockRequest, new String[] { "1" },
				"keyword", date, date);
	}

	@Test
	public final void testComposeTransactionsById() {

		servlet.setTransactionDao(mockTransactionDao);

		expect(mockTransactionDao.findById(Integer.valueOf(99))).andReturn(
				new Transaction(null, null, null, Float.valueOf("10"), null,
						null, null, false, null));
		mockRequest.setAttribute(eq("categoryAmount"), anyObject(Float.class));
		EasyMock.expectLastCall();

		replayMocks();

		servlet.composeTransactionsById(mockRequest, "99");
	}

	@Test
	public final void testComposeTransactionsUnconfirmed() {

		servlet.setTransactionDao(mockTransactionDao);
		servlet.setTransactionService(mockTransactionService);

		Transaction tran = new Transaction(null, null, null,
				Float.valueOf("10"), null, null, null, false, null);
		List<Transaction> list = new ArrayList<Transaction>();
		list.add(tran);

		expect(
				mockTransactionDao.findByAny(null, null, null, null, null,
						Boolean.FALSE)).andReturn(list);
		expect(mockTransactionService.calculateTransactionsTotal(list))
				.andReturn(Float.valueOf("10"));
		mockRequest.setAttribute(eq("categoryAmount"), anyObject(Float.class));
		EasyMock.expectLastCall();

		replayMocks();

		servlet.composeTransactionsUnconfirmed(mockRequest);
	}

	@Test
	public final void testComposeTransactionsByAccount() {

		servlet.setAccountDao(mockAccountDao);
		servlet.setTransactionDao(mockTransactionDao);

		Account acct = new Account(null, "testAcct", null, null, null, null, 0);

		expect(mockRequest.getParameter("acct")).andReturn("testAcct");
		expect(mockAccountDao.findByName("testAcct")).andReturn(acct);
		mockRequest.setAttribute("account", acct);
		EasyMock.expectLastCall();
		expect(
				mockTransactionDao.findByAny(anyObject(Category.class),
						anyObject(Date.class), anyObject(Date.class),
						eq("testAcct"), anyObject(String.class),
						anyObject(Boolean.class))).andReturn(null);

		replayMocks();

		servlet.composeTransactionsByAccount(mockRequest);
	}

	@Test
	public final void testPopulateDate() {

		expect(mockRequest.getParameter("test")).andReturn("01/20/1977");

		replayMocks();

		Date ret = servlet.populateDate(mockRequest, "test");
		assertNotNull(ret);
	}

	@Test
	public final void testDoPostSuccess() throws ServletException, IOException {

		Class[] args = { HttpServletRequest.class, HttpServletResponse.class };

		ShowTransactions partialMockServlet = (ShowTransactions) createPartialMock(
				ShowTransactions.class, "doPost", args, false);

		partialMockServlet.setAccountDao(mockAccountDao);
		partialMockServlet.setBudgetDao(mockBudgetDao);
		partialMockServlet.setCategoryDao(mockCategoryDao);
		partialMockServlet.setBudgetService(mockBudgetService);
		partialMockServlet.setCategoryService(mockCategoryService);
		partialMockServlet.setPageService(mockPageService);
		partialMockServlet.setTransactionService(mockTransactionService);

		Set<Category> cats = new TreeSet<Category>();
		List<Transaction> trans = new ArrayList<Transaction>();

		mockPageService.composeRequestLeftNav(mockRequest);
		EasyMock.expectLastCall();

		expect(mockRequest.getParameter("categoryThisMonth")).andReturn("test");
		expect(mockRequest.getParameter(anyObject(String.class))).andReturn(
				null).times(6);
		expect(
				partialMockServlet.createCategoryIdArray(
						anyObject(String.class), anyObject(String.class)))
				.andReturn(null);
		expect(
				partialMockServlet.populateDate(eq(mockRequest),
						anyObject(String.class))).andReturn(null).times(2);
		expect(
				partialMockServlet.composeTransactionsCurrentMonth(mockRequest,
						"test")).andReturn(trans);
		expect(mockCategoryDao.findAll()).andReturn(cats);
		mockRequest.setAttribute("allCategories", cats);
		EasyMock.expectLastCall();
		mockRequest.setAttribute("trans", trans);
		EasyMock.expectLastCall();

		expect(mockRequest.getRequestDispatcher(anyObject(String.class)))
				.andReturn(mockRequestDispatcher);
		mockRequestDispatcher.forward(mockRequest, mockResponse);
		EasyMock.expectLastCall();

		replayMocks();
		EasyMock.replay(partialMockServlet);

		partialMockServlet.doPost(mockRequest, mockResponse);

		EasyMock.verify(partialMockServlet);
	}
}
